module('lgx.decls.func', package.seeall)
local decl = require'lgx.decl'
local strbuf = require'lgx.strbuf'

local mt = decl.new()
mt.__index = mt

function new(o)
    o = decl.new(o)
    o.tag = decl.FUNC
    o.args = {}
	o.ellipsis = false
    o.defpos = 0
    setmetatable(o, mt)
    return o
end

function mt:addsub(tag, element)
    if tag == decl.FARG then
        table.insert(self.args, element)
		--if arg have no name, give it one^_^
		if #element.name == 0 then
			element.name = 'arg'..tostring(#self.args)
		end
        --if arg have default value, save begin position
        if element.default and self.defpos == 0 then
            self.defpos = #self.args
        end
	elseif tag == decl.ELLIPSIS then
		self.ellipsis = true
    end
end

function mt:iscopyctor()
    if self.tag ~= decl.CTOR then return false end
    if #self.args ~= 1 then return false end
    local argtype = self.ids[self.args[1].type]
    if argtype.tag ~= decl.RTYPE then return false end
    return argtype.type == (self.context..'c')
end

function mt:declargs_()
    local buf = strbuf.new()
    if #self.args < 1 then return buf end
    buf = buf + (self.ids:typename(self.args[1].type)..' '..(self.args[1].name or ''))
    if self:iscopyctor() then
        if not self.args[1].name then
            buf = buf + 'other'
        end
        return buf
    end
    for i=2, #self.args do
        buf = buf + (self.ids:typename(self.args[i].type)..' '..self.args[i].name)
    end
    return buf
end

function mt:declargs()
    return self:declargs_():concat(', ') or ''
end

function mt:callargs_()
    local buf = strbuf.new()
    if #self.args < 1 then return buf end
    if self:iscopyctor() then
        if not self.args[1].name then
            buf = buf + 'other'
        else
            buf = buf + self.args[1].name
        end
        return buf
    end
    for i=1,#self.args do
        buf = buf + self.args[i].name
    end
    return buf
end

function mt:callargs()
    return self:callargs_():concat(', ') or ''
end

function mt:protoargs_()
    local buf = strbuf.new()
    if #self.args < 1 then return buf end
    for i=1,#self.args do
        buf = buf + self:typename(self.args[i].type)
    end
    return buf
end

function mt:protoargs()
    return self:protoargs_():concat(', ') or ''
end

local nxrepmap = {
    [' ']  = '_',
    [',']  = '_',
    [':']  = '_',
    ['*']  = 'S',
    ['&']  = 'A',
	['<']  = '_',
	['>']  = '_',
}
function mt:nsnamex_()
    local args_ = string.gsub(self:protoargs(), '[ |,|:|*|&|>|<]', nxrepmap)
    return self:nsname_()..(#args_ > 0 and ('_'..args_) or '')
end
